package com.alibaba.csp.sentinel.dashboard.auth.jwt;

import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 用途描述：基于cookie的jwt认证，用于从cookie中获取jwt并反转为用户，支持集群部署
 * 1.用户登录时，验证用户密码，登录成功生成jwt并写入cookie，cookie有效期为浏览器回话结束
 * 2.用户访问需要验证的连接时，filter和interceptor通过CookieJwtAuthServiceImpl获取用户信息
 * 3.CookieJwtAuthServiceImpl从cookie中获取jwt并验证，验证成功生成用户返回
 * 4.用户注销时删除cookie
 * <p>
 * jwt理论上为无状态认证token，但为了方便扩展，设计一个jwt和用户的映射存储接口。
 *
 * @author YangLong
 * @version V1.0
 * @since 2024/2/23
 */
public class CookieJwtAuthServiceImpl implements AuthService<HttpServletRequest> {
    public static final String TOKEN_COOKIE_NAME = "sentinel_jwt";

    private TokenConverter tokenConverter;

    //@Autowired
    //private TokenStore tokenStore;


    public CookieJwtAuthServiceImpl(TokenConverter tokenConverter) {
        this.tokenConverter = tokenConverter;
    }

    @Override
    public AuthUser getAuthUser(HttpServletRequest request) {
        //获取cookie中的jwt
        String token = getAuthToken(request);
        if (StringUtils.isNotBlank(token)) {
            //从jwt反解出用户信息
            JwtUser user = tokenConverter.convertToken(token);
            //if (null != user) {
            //这里可以从tokenStore中读取全部信息-包括权限角色，配合AuthUser验证方法实现权限验证
            //user = tokenStore.readUser(user.getTokenId());
            //}
            return user;
        }
        return null;
    }

    /**
     * 提取请求头
     *
     * @param request 请求
     * @return 请求头
     */
    protected String getAuthToken(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        String token = null;
        if (null != cookies) {
            for (Cookie c : cookies) {
                if (Objects.equals(c.getName(), TOKEN_COOKIE_NAME)) {
                    token = c.getValue();
                    break;
                }
            }
        }
        return token;
    }

}
